package com.me.waterphase;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.Iterator;


import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL10;

import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.BodyDef.BodyType;
import com.me.waterphase.utils.DebugInfo;
import com.me.waterphase.utils.PhysicManager;

/*
 * Game world, called by WaterPhase that implements the ApplicationListener.
 */
public class WaterWorld {

		public static WaterWorld world;
	
		private WaterPlayer player;
		private WaterArtifact artifact;
		private WaterEnergySource source;
		
		private float globalTemperature;
		
		private ArrayList<WaterImmobileObject> staticObjects;
		private static SpriteBatch stage;
		
		public DebugInfo debugHud;
		
		private float stateTime;
		private static WaterCamera camera;
						
		private WaterWorld(){

			stateTime = 0f;
			
			artifact = new WaterArtifact(35, 50, 5,5);
			player = new WaterPlayer(GraphicManager.WALKING_MAN, 0, 50, 20f, 20f, WaterPlayer.PLAYER_STATE.MEDIUM, 24f);
			source = new WaterEnergySource(200, 0, 25, 50, -5);
			
			//Set the global temperature of the world.
			globalTemperature = 24f;
			
			camera = new WaterCamera();		
			camera.getOrthoCamera().zoom = 0.75f;
						
			loadMap("carte_test.map");
			
			//Creation of the debug HUD.
			debugHud = new DebugInfo();
		}
		
		public void dispose()
		{
			stage.dispose();
		}
		
		public static SpriteBatch getStage(){
			if(stage == null){
				stage = new SpriteBatch();
			}
			
			return stage;
		}
		
		/*
		 * World singleton.
		 */
		public static WaterWorld getInstance()
		{
			if(world == null)
			{
				world = new WaterWorld();
			}
			
			return world;
		}
				
	
		/*
		 * Main loop of in-game level.
		 */
		public void render(){
			
			Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);                                        
			stateTime += Gdx.graphics.getDeltaTime();
			
			//Affect the world's elements with numerous factor.
			resolveTemperature();
						
			//Move objects.
	        player.preUpdate();  
	        PhysicManager.Update(stateTime);
	        
	        //Process after physic world update.
	        player.postUpdate();
	        //Render of camera moved in the post-update function.
	        postUpdate();
	        
	        //Rendering...
	        player.render(stateTime);
	        
	        //Render all the immobile objects.
			for(Iterator<WaterImmobileObject> i = staticObjects.iterator(); i.hasNext();){
	        	i.next().render();	
	        }
				
			//Add information to be shown in debug.
			debugHud.addLine("Foot contact", String.valueOf(player.getFootContact().getNumberContact()));			
			
			if(player.getArtifact() != null)
				debugHud.addLine("Artifact contact", String.valueOf(player.getArtifact().getArtifactContact().getNumberContact()));
			
			debugHud.addLine("Gravity scale", String.valueOf(player.getBody().getGravityScale()));
			debugHud.addLine("Temperature", String.valueOf(player.getTemperature()));
			debugHud.addLine("GravDisabled", String.valueOf(player.isGravityDisabled()));
			debugHud.addLine("State", String.valueOf(player.getState()));
			
			debugHud.render();
	    }
		
		private void loadMap(String _mapName)
		{
			
			//A simple platform to test.
			staticObjects = new ArrayList<WaterImmobileObject>();
			staticObjects.add(new WaterImmobileObject(GraphicManager.WALL, 0, 0, 1024f, 16f));
			staticObjects.add(new WaterImmobileObject(GraphicManager.WALL, 100, 0, 16f, 95f));

			//List to create a slope. Error if clockwise, must be counter-clockwise.
			ArrayList<Vector2> slope = new ArrayList<Vector2>();
			slope.add(new Vector2(4, 0.25f));
			slope.add(new Vector2(6, 0.25f));
			slope.add(new Vector2(5,1.25f));
			
			PhysicManager.createPolyBody(BodyType.StaticBody,0f,0f, 0f,0f,0f, slope.toArray(new Vector2[0]), true);
			
			//TODO: Parse XML file to load positions and objects.
			try {
				FileReader map = new FileReader("../maps/" + _mapName);
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			}			
		}
		
		/*
		 * Treatment in the physic world Update, at the end.
		 */
		public void postUpdate(){
			
			//Update camera.
	        camera.lookAt(player.getCenter());
	        camera.render();
	        
	        //Information for debug camera.	        
	        PhysicManager.renderDebug(new Vector2(camera.getOrthoCamera().position.x, camera.getOrthoCamera().position.y));
		}
		
		//Process related to global temperature and energy sources.
		private void resolveTemperature()
		{
			if(player.getTemperature() != globalTemperature && !source.getAffectedObjects().contains(player))
			{
				if(Math.abs(player.getTemperature() - globalTemperature) < 1)
					player.setTemperature(globalTemperature);
				else
				{
					//Reduce gap between the player temperature and the world one.
					player.setTemperature(player.getTemperature() - (player.getTemperature()-globalTemperature)*0.00005f);
				}
			}

			//Clean affected objects in energy sources.
			source.getAffectedObjects().clear();
		}
		
		
		//Getter.
		public WaterPlayer getPlayer(){return player;}
		public WaterArtifact getArtifact(){return artifact;}
				
}
